#include "CBlockCollection.h"
#include "CRegionSceneNode.h"

CBlockCollection::CBlockCollection()
{
	BatchMesh = 0;
	Visible = false;
	HasBox = false;
}

CBlockCollection::~CBlockCollection()
{
	if(BatchMesh)
		BatchMesh->drop();
}

void CBlockCollection::addBlock(CBlockSceneNode *block)
{
	Blocks.push_back(block);
//	aabbox3df box(block->getAbsolutePosition(), block->getAbsolutePosition() + vector3df(1,1,1));
//	BoundingBox.addInternalBox(box);
	if(HasBox)
	{
		BoundingBox.addInternalBox(block->getTransformedBoundingBox());
	}
	else
	{
		HasBox = true;
		BoundingBox = block->getTransformedBoundingBox();
	}
}

void CBlockCollection::updateTiles()
{
	if(BatchMesh)
		return;
	
	BatchMesh = new CBatchingMesh();
//	BatchMesh->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX_AND_INDEX);

	u32 c = 0;

	u32 bc = Blocks.size();
	for(u32 bi = 0; bi < bc; bi++)
	{
		CBlockSceneNode *b = Blocks[bi];
		b->updateTiles();
		u32 tc = b->getTileCount();
		for(u32 ti = 0; ti < tc; ti++)
		{
			CTile *t = b->getTile(ti);
			if(t && t->Visible && t->Material && t->Resource && t->Resource->Mesh)
			{
				for(u32 mbi = 0; mbi < t->Resource->Mesh->getMeshBufferCount(); mbi++, c++)
					BatchMesh->addMeshBuffer(t->Resource->Mesh->getMeshBuffer(mbi), b->getRelativeTransformation() * t->getRelativeTransformation() * t->Resource->getTransformation(), &t->Material->Material);
			}
		}
	}
	BatchMesh->finalize();

//	for(u32 i = 0; i < BatchMesh->getMeshBufferCount(); i++)
//		printf("%d ", BatchMesh->getMeshBuffer(i)->getVertexCount());
//	printf("\n");
	//printf("%d/%d meshbuffers\n", BatchMesh->getMeshBufferCount(), c);
}

void CBlockCollection::render(bool batch)
{
	if(Blocks.size() == 0) return;

	if(batch && BatchMesh)
	{
		IVideoDriver *video = Blocks[0]->getSceneManager()->getVideoDriver();
		video->setTransform(ETS_WORLD, matrix4());
		u32 c = BatchMesh->getMeshBufferCount();
		for(u32 i = 0; i < c; i++)
		{
			IMeshBuffer *mb = BatchMesh->getMeshBuffer(i);
//			video->setTransform(ETS_WORLD, Blocks[0]->getRegion()->getAbsoluteTransformation());
			video->setMaterial(mb->getMaterial());
			video->drawMeshBuffer(mb);
		}
		c = Blocks.size();
		for(u32 i = 0; i < c; i++)
			Blocks[i]->renderBuildings();
	}
	else
	{
		u32 c = Blocks.size();
		for(u32 i = 0; i < c; i++)
		{
			Blocks[i]->render();
		}
	}
}

void CBlockCollection::removeBlock(CBlockSceneNode *block)
{
	u32 c = Blocks.size();
	for(u32 i = 0; i < c; i++)
	{
		if(Blocks[i] == block)
		{
			Blocks.erase(i);
			return;
		}
	}
}

void CBlockCollection::removeBlock(u32 i)
{
	Blocks.erase(i);
}

u32 CBlockCollection::getBlockCount() const
{
	return Blocks.size();
}

void CBlockCollection::getBlocks(array<CBlockSceneNode*> &blocks)
{
	blocks = Blocks;
}

const aabbox3df& CBlockCollection::getBoundingBox() const
{
	return BoundingBox;
}